import { playerChance, TikTok } from "./utils.js";
import {
    PlayGroundWidth,
    PlayGroundHeight,
} from "./canvas.js";

const BonusShapeWidth = 8;
const BonusShapeHeight = 8;

// 地图
let _currentMap = null;
export class GameMap {
    constructor(opt = {}) {
        let { bricks = [] } = opt;
        this._brickStore = bricks.map(brick => {
            return new Brick({
                parent: this,
                type: brick.type,
                coord: {
                    x: brick[0],
                    y: brick[1],
                },
            });
        });
        this._base = new Brick({
            parent: this,
            type: "base",
            coord: {
                x: 100,
                y: 165,
            },
        });
        this._brickStore.push(this._base);
        this._baseGuards = [
            [90, 175], [90, 170], [90, 165], [90, 160],
            [95, 175], [95, 170], [95, 165], [95, 160],
            [100, 160], [105, 160], [110, 160], [115, 160],
            [120, 175], [120, 170], [120, 165], [120, 160],
            [125, 175], [125, 170], [125, 165], [125, 160],
        ].map(brick => {
            return new Brick({
                parent: this,
                type: brick.type,
                coord: {
                    x: brick[0],
                    y: brick[1],
                },
            });
        });
        this._brickStore.push(...this._baseGuards);

        this._bonus = null;
        this._bonusTime = 2;
        this._randomBonus = () => {
            if (this._bonusTime) {
                this._bonusTime--;
            } else {
                if (this._bonus) {
                    this._bonus.destroy();
                    this._bonus = null;
                } else {
                    if (Math.random() < 0.25) {
                        this._bonusTime = 2;
                        let _type = ["bonusLive", "bonusPower", "bonusBase"];
                        this._bonus = new Brick({
                            parent: this,
                            type: _type[Math.floor(Math.random() * 2)],
                            coord: {
                                x: Math.floor(Math.random() * PlayGroundWidth - BonusShapeWidth),
                                y: Math.floor(Math.random() * PlayGroundHeight - BonusShapeHeight),
                            },
                        });
                        this._brickStore.push(this._bonus);
                    }
                }
            }
        };
        TikTok.register(this._randomBonus, 800);
        _currentMap = this;
    }

    switchBaseGuard(type) {
        this._baseGuards.forEach(brick => {
            let _index = this._brickStore.findIndex(item => item === brick);
            this._brickStore.splice(_index, 1);
        });
        let _baseGuards = [
            [90, 175], [90, 170], [90, 165], [90, 160],
            [100, 160], [110, 160],
            [120, 175], [120, 170], [120, 165], [120, 160],
        ];
        if (type === "normalBaseGuard") {
            this._baseGuards = _baseGuards.map(brick => {
                return new Brick({
                    parent: this,
                    coord: {
                        x: brick[0],
                        y: brick[1],
                    },
                });
            });
        } else if (type === "strongerBaseGuard") {
            this._baseGuards = _baseGuards.map(brick => {
                return new Brick({
                    parent: this,
                    type: "hard",
                    coord: {
                        x: brick[0],
                        y: brick[1],
                    },
                });
            });
        } else {
            // noneBaseGuard
            this._baseGuards = [];
        }
        this._brickStore.push(...this._baseGuards);
    }

    getType() {
        return "map";
    }

    getPlayerCoord(name) {
        if (name === "player1") {
            return { x: 75, y: 170 };
        } else if (name === "player2") {
            return { x: 140, y: 170 };
        } else {
            return { x: 0, y: 0 };
        }
    }

    showNoChanceTip(name) {
        this._brickStore.push(new Brick({
            parent: this,
            type: "noChanceTip",
            coord: this.getPlayerCoord(name),
        }));
    }

    hideNoChanceTip(name) {
        let _coord = this.getPlayerCoord(name);
        let _index = this._brickStore.findIndex(brick => {
            return brick.type === "noChanceTip" && brick.coord.x === _coord.x && brick.coord.y === _coord.y;
        });
        this._brickStore.splice(_index, 1);
    }

    getMap() {
        return this._brickStore.reduce((acc, brick) => {
            acc.push(...brick.shape.map(graph => {
                let _arr;
                if (graph && graph.opt.type === "text") {
                    _arr = graph;
                } else {
                    _arr = graph.map(item => [item[0] + brick.coord.x, item[1] + brick.coord.y]);
                    _arr.opt = graph.opt;
                }
                return _arr;
            }));
            return acc;
        }, []);
    }

    add() {}

    remove() {}

    removeBrick(target) {
        let _index = this._brickStore.findIndex(item => item === target);
        this._brickStore.splice(_index, 1);
    }

    destroy() {
        TikTok.unRegister(this._randomBonus);
        this._bonus = null;
        this._bonusTime = 2;
    }

    static getCurrentMap() {
        return _currentMap;
    }
}

// 砖头(大小必须不小于tank，才能保证击碎一块之后能通过)
class Brick {
    constructor(opt = {}) {
        const { coord, parent, type = "normal" } = opt;
        this.parent = parent;
        this.type = type;
        this.canBeHitByBullet = true;       // 能被bullet击中
        this.canBeHitByPlayer = true;       // 能被tank撞上
        this.canBeHitByRobot = true;
        this.shape = [[[0, 0], [5, 0], [5, 5], [0, 5]]];
        this.shapeWidth = 5;
        this.shapeHeight = 5;
        this.shape[0].opt = {
            fillColor: "#ba6c1f",
            strokeColor: "#ffffff",
        };
        this.coord = {
            x: coord.x,
            y: coord.y,
        };

        if (type === "hard") {
            this.shape[0].opt = {
                fillColor: "#ffffff",
                strokeColor: "#9f9f9f",
            };
        } else if (type === "base") {
            this.shape = [[
                [0, 0], [4, 2], [8, 7], [10, 2], [8, 2], [10, 0],
                [12, 7], [16, 2], [20, 0],
                [15, 10], [12, 10], [12, 13], [16, 15],
                [4, 15], [8, 13], [8, 10], [5, 10],
            ]];
            this.shapeWidth = 20;
            this.shapeHeight = 15;
            this.shape[0].opt = {
                fillColor: "#6f6f6f",
            };
        } else if (type === "noChanceTip") {
            this.shape = [new String("NO LIVE")];
            this.shape[0].opt = {
                type: "text",
                font: "22px gray",
                x: this.coord.x,
                y: this.coord.y,
            };
            this.canBeHitByBullet = false;
            this.canBeHitByPlayer = false;
            this.canBeHitByRobot = false;
        } else if (type === "bonusLive") {
            this.shape = [[
                [0, 0], [8, 0], [8, 8], [0, 8],
            ], [
                [1, 1], [6, 1], [6, 2], [4, 2], [4, 3],
                [5, 4], [7, 4], [5, 4], [4, 5],
                [4, 6], [6, 6], [6, 7],
                [1, 7], [1, 6], [2, 6], [2, 5],
                [1, 4], [2, 3], [2, 2], [1, 2],
            ]];
            this.shapeWidth = BonusShapeWidth;
            this.shapeHeight = BonusShapeHeight;
            this.shape[0].opt = {
                strokeColor: "#ffffff",
                lineWidth: 1,
            };
            this.shape[1].opt = {
                strokeColor: "#ffffff",
                lineWidth: 2,
            };
            this.canBeHitByBullet = false;
            this.canBeHitByPlayer = true;
            this.canBeHitByRobot = false;
        } else if (type === "bonusPower") {
            this.shape = [[
                [0, 0], [8, 0], [8, 8], [0, 8],
            ], [
                [4, 0], [7, 8], [0, 3], [8, 3], [1, 8],
            ]];
            this.shapeWidth = BonusShapeWidth;
            this.shapeHeight = BonusShapeHeight;
            this.shape[0].opt = {
                strokeColor: "#ffffff",
                lineWidth: 1,
            };
            this.shape[1].opt = {
                fillColor: "#ffffff",
                lineWidth: 2,
            };
            this.canBeHitByBullet = false;
            this.canBeHitByPlayer = true;
            this.canBeHitByRobot = true;
        } else if (type === "bonusBase") {
            this.shape = [[
                [0, 0], [8, 0], [8, 8], [0, 8],
            ], [
                [1, 4], [2, 3], [3, 4], [6, 1], [7, 2],
                [4, 5], [5, 6], [4, 7], [2, 7], [1, 6],
            ]];
            this.shapeWidth = BonusShapeWidth;
            this.shapeHeight = BonusShapeHeight;
            this.shape[0].opt = {
                strokeColor: "#ffffff",
                lineWidth: 1,
            };
            this.shape[1].opt = {
                fillColor: "#ffffff",
                lineWidth: 2,
            };
            this.canBeHitByBullet = false;
            this.canBeHitByPlayer = true;
            this.canBeHitByRobot = true;
        }
    }

    getType() {
        return "brick";
    }

    // 被击中
    beShot(byTarget) {
        if (byTarget.getType() === "bullet") {
            if (this.type === "base") {
                alert("oops! our base was been destroyed, game over!");
            } else if (this.type === "hard" && byTarget.power === 1) {
                // pass
            } else {
                this.destroy();
            }
        } else if (byTarget.getType() === "tank") {
            if (this.type === "bonusLive" && (byTarget.name === "player1" || byTarget.name === "player2")) {
                this.parent._bonus.destroy();
                this.parent._bonus = null;
                this.parent._bonusTime = 0;
                playerChance[byTarget.name]++;
            } else if (this.type === "bonusPower") {
                this.parent._bonus.destroy();
                this.parent._bonus = null;
                this.parent._bonusTime = 0;
                if (byTarget.parent.getType() === "robot") {
                    byTarget.switchType("strongerRobot");
                } else if (byTarget.parent.getType() === "player") {
                    byTarget.switchType("strongerPlayer");
                }
            } else if (this.type === "bonusBase") {
                this.parent._bonus.destroy();
                this.parent._bonus = null;
                this.parent._bonusTime = 0;
                if (byTarget.parent.getType() === "robot") {
                    this.parent.switchBaseGuard("");
                } else if (byTarget.parent.getType() === "player") {
                    this.parent.switchBaseGuard("strongerBaseGuard");
                }
            }
        }
    }

    destroy() {
        this.parent.removeBrick(this);
    }
}

export function generateMap1() {
    let coords = [
        [100, 40], [105, 40], [110, 40],
        [100, 45], [105, 45], [110, 45],
        [0, 85], [5, 85], [10, 85], [15, 85],
        [0, 90], [5, 90], [10, 90], [15, 90],
        [200, 85], [200, 90], [205, 85], [205, 90], [210, 85], [210, 90], [215, 85], [215, 90],
    ];
    coords.forEach(brick => { brick.type = "hard"; });

    for (let i = 15; i <= 30; i += 5) {
        for (let j = 10; j <= 60; j += 5) {
            coords.push([i, j]);
        }
    }
    for (let i = 50; i <= 65; i += 5) {
        for (let j = 10; j <= 60; j += 5) {
            coords.push([i, j]);
        }
    }
    for (let i = 85; i <= 100; i += 5) {
        for (let j = 10; j <= 50; j += 5) {
            coords.push([i, j]);
        }
    }
    for (let i = 115; i <= 130; i += 5) {
        for (let j = 10; j <= 50; j += 5) {
            coords.push([i, j]);
        }
    }
    for (let i = 150; i <= 165; i += 5) {
        for (let j = 10; j <= 60; j += 5) {
            coords.push([i, j]);
        }
    }
    for (let i = 185; i <= 200; i += 5) {
        for (let j = 10; j <= 60; j += 5) {
            coords.push([i, j]);
        }
    }

    for (let i = 35; i <= 60; i += 5) {
        for (let j = 85; j <= 90; j += 5) {
            coords.push([i, j]);
        }
    }
    coords.push([85, 70], [90, 70], [95, 70], [100, 70],
                [85, 75], [90, 75], [95, 75], [100, 75]);
    coords.push([115, 70], [120, 70], [125, 70], [130, 70],
                [115, 75], [120, 75], [125, 75], [130, 75],);
    for (let i = 155; i <= 180; i += 5) {
        for (let j = 85; j <= 90; j += 5) {
            coords.push([i, j]);
        }
    }

    for (let i = 15; i <= 30; i += 5) {
        for (let j = 120; j <= 160; j += 5) {
            coords.push([i, j]);
        }
    }
    for (let i = 50; i <= 65; i += 5) {
        for (let j = 120; j <= 160; j += 5) {
            coords.push([i, j]);
        }
    }
    for (let i = 85; i <= 100; i += 5) {
        for (let j = 100; j <= 140; j += 5) {
            coords.push([i, j]);
        }
    }
    coords.push([105, 100], [110, 100],
                [105, 115], [110, 115],
                [105, 120], [110, 120]);
    for (let i = 115; i <= 130; i += 5) {
        for (let j = 100; j <= 140; j += 5) {
            coords.push([i, j]);
        }
    }
    for (let i = 150; i <= 165; i += 5) {
        for (let j = 120; j <= 160; j += 5) {
            coords.push([i, j]);
        }
    }
    for (let i = 185; i <= 200; i += 5) {
        for (let j = 120; j <= 160; j += 5) {
            coords.push([i, j]);
        }
    }

    return new GameMap({
        bricks: coords,
    });
}
